#include "Servlet.h"
#include <fnmatch.h>

namespace sylar
{
namespace http
{
	Servlet::Servlet(const std::string& name) :m_name(name)
	{
	}

	Servlet::~Servlet()
	{
	}

	FunctionSerlet::FunctionSerlet(CallBacke cb) :Servlet("FunctionSerlet"),m_cb(cb)
	{
	}

	int32_t FunctionSerlet::handle(sylar::http::HttpRequest::ptr request, sylar::http::HttpResponse::ptr response, sylar::http::HttpSession::ptr session)
	{
		if (!m_cb)
		{
			return -1;
		}
		return m_cb(request, response, session);
	}

	ServletDispatch::ServletDispatch() :Servlet("ServletDispatch"),m_default(new NotFunctDefualt)
	{

	}

	int32_t ServletDispatch::handle(sylar::http::HttpRequest::ptr request, sylar::http::HttpResponse::ptr response, sylar::http::HttpSession::ptr session)
	{
		auto slt = getMatchedServlet(request->getPath());
		if (slt)
		{
			return slt->handle(request, response, session);
		}

		return 0;
	}

	void ServletDispatch::addServlet(const std::string& uri, Servlet::ptr slt)
	{
		RWMutex::WriteLock wlock(rwmutx);
		m_data[uri] = slt;
	}

	void ServletDispatch::addServlet(const std::string& uri, FunctionSerlet::CallBacke cb)
	{
		RWMutex::WriteLock wlock(rwmutx);
		m_data[uri] = std::make_shared<FunctionSerlet>(cb);
	}

	void ServletDispatch::addServletGlobs(const std::string& uri, Servlet::ptr slt)
	{
		RWMutex::WriteLock wlock(rwmutx);

		for (auto it =m_globs.begin() ;it!=m_globs.end();it++)
		{
			if (it->first == uri)
			{
				m_globs.erase(it);
				break;
			}
		}
		m_globs.push_back(std::make_pair(uri, slt));
	
	}

	void ServletDispatch::addServletGlobs(const std::string& uri, FunctionSerlet::CallBacke cb)
	{
		RWMutex::WriteLock wlock(rwmutx);
		addServletGlobs(uri,std::make_shared<FunctionSerlet>(cb));
	
	}

	void ServletDispatch::delServlet(const std::string& uri)
	{
		RWMutex::WriteLock wlock(rwmutx);
		m_data.erase(uri);
	}

	void ServletDispatch::delServletGlobs(const std::string& uri)
	{
		RWMutex::WriteLock wlock(rwmutx);
		for (auto it = m_globs.begin(); it != m_globs.end(); it++)
		{
			if (it->first == uri)
			{
				m_globs.erase(it);
				break;
			}
		}
	}

	Servlet::ptr ServletDispatch::getServlet(const std::string& uri)
	{
		RWMutex::ReadLock rlock(rwmutx);

		auto it = m_data.find(uri);
		if (it == m_data.end())
		{
			return nullptr;
		}
	
		return it->second;
	}

	Servlet::ptr ServletDispatch::getServletGlobs(const std::string& uri)
	{
		RWMutex::ReadLock rlock(rwmutx);
		for (auto it = m_globs.begin(); it != m_globs.end(); it++)
		{
			if (!fnmatch(it->first.c_str(), uri.c_str(), 0))
			{
				return it->second;
			}
		}
		return nullptr;
	}

	Servlet::ptr ServletDispatch::getMatchedServlet(const std::string& uri)
	{
		RWMutex::ReadLock lock(rwmutx);
		auto mit = m_data.find(uri);
		if (mit != m_data.end()) {
			return mit->second;
		}
		for (auto it = m_globs.begin();
			it != m_globs.end(); ++it) {
			if (!fnmatch(it->first.c_str(), uri.c_str(), 0)) {
				return it->second;
			}
		}
		return m_default;
	}

	
	NotFunctDefualt::NotFunctDefualt():Servlet("NotFunctDefualt")
	{

	}

	int32_t NotFunctDefualt::handle(sylar::http::HttpRequest::ptr request, sylar::http::HttpResponse::ptr response, sylar::http::HttpSession::ptr session)
	{
		//TDTO

		response->setStatus(HttpStatus::NOT_FOUND);
		response->setHeader("content-type", "text/html");
		//response->setBody();

		return 0;
	}

}
}
